Program Listing for File initial_pose_factor.h

Return to documentation for file (codes/slam/factor/initial_pose_factor.h)

/*******************************************************
 * Copyright (C) 2019, Robotics Group, Nanyang Technology University
 *
 * This file is part of sslam.
 *
 * Licensed under the GNU General Public License v3.0;
 * you may not use this file except in compliance with the License.
 *
 * Author: Zhang Handuo (hzhang032@e.ntu.edu.sg)
 *******************************************************/

#pragma once

#include <ros/assert.h>
#include <ceres/ceres.h>
#include <Eigen/Dense>
#include "../utility/utility.h"
#include "../utility/tic_toc.h"
#include "../estimator/parameters.h"

namespace noiseFactor {
    class InitialPoseFactor : public ceres::SizedCostFunction<6, 7> {
    public:
    #ifndef DOXYGEN_SHOULD_SKIP_THIS

        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
    #endif /* DOXYGEN_SHOULD_SKIP_THIS */

        InitialPoseFactor(const Eigen::Vector3d &_P, const Eigen::Quaterniond &_Q) {
            init_P = _P;
            init_Q = _Q;
            sqrt_info = 1000 * Eigen::Matrix<double, 6, 6>::Identity();
        }

        virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const {
            Eigen::Vector3d P(parameters[0][0], parameters[0][1], parameters[0][2]);
            Eigen::Quaterniond Q(parameters[0][6], parameters[0][3], parameters[0][4], parameters[0][5]);

            Eigen::Map<Eigen::Matrix<double, 6, 1>> residual(residuals);
            residual.block<3, 1>(0, 0) = P - init_P;
            residual.block<3, 1>(3, 0) = 2 * (init_Q.inverse() * Q).vec();
            residual = sqrt_info * residual;

            if (jacobians) {
                if (jacobians[0]) {
                    Eigen::Map<Eigen::Matrix<double, 6, 7, Eigen::RowMajor>> jacobian_pose(jacobians[0]);
                    jacobian_pose.setZero();
                    jacobian_pose.block<3, 3>(0, 0) = Eigen::Matrix3d::Identity();
                    jacobian_pose.block<3, 3>(3, 3) = Utility::Qleft(init_Q.inverse() * Q).bottomRightCorner<3, 3>();
                    jacobian_pose = sqrt_info * jacobian_pose;
                }

            }
            return true;

        }

        void check(double **parameters) {
            double *res = new double[6];
            double **jaco = new double *[1];
            jaco[0] = new double[6 * 7];
            Evaluate(parameters, res, jaco);
            puts("check begins");

            puts("my");

            std::cout << Eigen::Map<Eigen::Matrix<double, 6, 1>>(res).transpose() << std::endl
                      << std::endl;
            std::cout << Eigen::Map<Eigen::Matrix<double, 6, 7, Eigen::RowMajor>>(jaco[0]) << std::endl
                      << std::endl;

            Eigen::Vector3d P(parameters[0][0], parameters[0][1], parameters[0][2]);
            Eigen::Quaterniond Q(parameters[0][6], parameters[0][3], parameters[0][4], parameters[0][5]);

            Eigen::Matrix<double, 6, 1> residual;
            residual.block<3, 1>(0, 0) = P - init_P;
            residual.block<3, 1>(3, 0) = 2 * (init_Q.inverse() * Q).vec();
            residual = sqrt_info * residual;

            puts("num");
            std::cout << residual.transpose() << std::endl;

            const double eps = 1e-6;
            Eigen::Matrix<double, 6, 6> num_jacobian;
            for (int k = 0; k < 6; k++) {
                Eigen::Vector3d P(parameters[0][0], parameters[0][1], parameters[0][2]);
                Eigen::Quaterniond Q(parameters[0][6], parameters[0][3], parameters[0][4], parameters[0][5]);

                int a = k / 3, b = k % 3;
                Eigen::Vector3d delta = Eigen::Vector3d(b == 0, b == 1, b == 2) * eps;

                if (a == 0)
                    P += delta;
                else if (a == 1)
                    Q = Q * Utility::deltaQ(delta);


                Eigen::Matrix<double, 6, 1> tmp_residual;
                tmp_residual.block<3, 1>(0, 0) = P - init_P;
                tmp_residual.block<3, 1>(3, 0) = 2 * (init_Q.inverse() * Q).vec();
                tmp_residual = sqrt_info * tmp_residual;

                num_jacobian.col(k) = (tmp_residual - residual) / eps;
            }
            std::cout << num_jacobian << std::endl;

        }

        Eigen::Vector3d init_P;
        Eigen::Quaterniond init_Q;
        Eigen::Matrix<double, 6, 6> sqrt_info;
    };
}